/**
 * 对称加密算法AES和3DES的实现,CBC模式下需要初始化向量,ECB模式下不需要
 * 需要前后端统一密钥，可以通过RSA加密后传输
 * 对称加密场景：
 */
export class AESCrypto {
  /**
   * 密钥
   */
  private key: string
  /**
   * 初始化向量,16字节,作用是防止相同的明文加密后得到相同的密文,CBC模式下需要
   */
  private iv: CryptoJS.lib.WordArray
  /**
   * 密钥字符串,32字节
   */
  private keyWordArray: CryptoJS.lib.WordArray

  /**
   * 构造函数
   * @param key 密钥
   */
  constructor(key: string) {
    if (!key || key.length < 32) {
      throw new Error('AES密钥长度至少需要32个字符')
    } else {
      this.key = key.substring(0, 32)
      this.iv = CryptoJS.enc.Utf8.parse(key.substring(0, 16))
      this.keyWordArray = CryptoJS.enc.Utf8.parse(this.key)
    }
  }
  /**
   * 加密
   * @param plaintext 明文
   * @returns 加密后的密文
   */
  encrypt(plaintext: string) {
    const encrypted = CryptoJS.AES.encrypt(plaintext, this.keyWordArray, {
      mode: CryptoJS.mode.CBC,
      iv: this.iv,
      padding: CryptoJS.pad.Pkcs7,
    })
    return encrypted.toString()
  }
  /**
   * 解密
   * @param ciphertext 密文
   * @returns 解密后的明文
   */
  decrypt(ciphertext: string) {
    const decrypted = CryptoJS.AES.decrypt(ciphertext, this.keyWordArray, {
      mode: CryptoJS.mode.CBC,
      iv: this.iv,
      padding: CryptoJS.pad.Pkcs7,
    })
    return decrypted.toString(CryptoJS.enc.Utf8)
  }
}
